/****************************************************
 ****************************************************
 ***                                              ***
 ***   Project:  YAVRS                            ***
 ***   (Yet Another Virtual Reality System)       ***
 ***   ________________________________________   ***
 ***                                              ***
 ***   File:     yavrsCamera.h                    ***
 ***   Authors:  Steve Conner & Thomas Marrinan   ***
 ***   Date:     09/28/2011                       ***
 ***                                              ***
 ****************************************************
 ****************************************************/

#ifndef __YAVRS_CAMERA_H
#define __YAVRS_CAMERA_H


#ifdef __APPLE__
#include <GLUT/glut.h>
#endif
#ifndef __APPLE__
#include <GL/glut.h>
#endif

#define PI 3.14159265359

//! List of available stereo modes
enum stereo_mode { NONE, LEFT_EYE, RIGHT_EYE, INTERLEAVED, SIDE_BY_SIDE };
enum interaction_mode { FREE_ROTATE, FIRST_PERSON };

//! Brief description
class yavrsCamera {
private:
	/*** Members ***/
	int width_px;             // window width  - pixels
	int height_px;            // window height - pixels
	double width_m;           // window width  - meters
	double height_m;          // window height - meters
	int screenW_px;           // screen width  - pixels
	int screenH_px;           // screen height - pixels
	double m_per_px;          // meters per pixel (the length of 1 pixel)
	double cw[3];             // position of the center of the window - world coordinates
	double vpn[3];            // vector pointing into the window - world coordinates
	double viewUp[3];         // vector pointing up the y-axis of the window - world coordinates
	double cop[3];            // position of the Center Of Projection - relative to window orientation
	stereo_mode mode;         // specifies rendering mode
    interaction_mode iMode;   // specifies the rotation interaction
	void (*renderFunction)(); // specifies the rendering function 
	
public:
	/*! Constructor/Destructor */
	yavrsCamera(int w, int h, const char* cfgFile);
	~yavrsCamera() {};
	
	//! Update window configuration when user resizes
	/*!
	 * \param w Width
	 * \param h Height
	*/
	void resize(int w, int h);

	//! Function to render objects
	void renderFunc(void (*f)());

	//! Draws the scene according to stereo mode
	void renderScene();

	//! Set up view properties
	void setView(double winCen[], double camDir[], double camUp[], double projCen[]);

	//! Set the stereo rendering mode
	void setStereoMode(stereo_mode m);
    
    //! Set the user interaction mode
    void setInteractionMode(interaction_mode m);
	
	//! Set the center of projection
	void setCOP(double x, double y, double z);

	//! Set the center of projection
	void setOrientation(double x, double y, double z, double w);

	//! Translate the center of projection
	void translateCOP(double x, double y, double z);

	//! Translate the window in the virtual world
	void translateCamera(double x, double y, double z);  

	//! Rotate window about a world-axis
	void rotateCamera(double axis[], double deg);

	//! Rotate window about cop's local x-axis (positive)
	void lookUp(double deg);

	//! Rotate window about cop's local x-axis (negative)
	void lookDown(double deg);

	//! Rotate window about cop's local y-axis (positive)
	void lookLeft(double deg);

	//! Rotate window about cop's local y-axis (negative)
	void lookRight(double deg);

	//! Rotate window about cop's local z-axis (positive)
	void lookClockWise(double deg);

	//! Rotate window about cop's local z-axis (negative)
	void lookCounterClockWise(double deg);

	//! Converts a point in view coordinates to world coordinates
	void vrc2world(double vrcPt[], double worldPt[]);

	//! Get the screen size in pixels
	void getScreenSize(int size[]);
	
	//! Get the location of the cop in world coordinates
	void getCameraPosition(double cop_wc[]);

	//! Get Viewing Window direction
	void getWindowDirection(double windowDir[]);

	//! Get View Window up
	void getWindowUp(double windowUp[]);

	//! Get window center in world coordinates
	void getWindowCenter(double windowCenter[]);

	//! Get the location of the right-top corner of the window in world coordinates
	void getWindowRT(double windowRT[]);

	//! Get the location fo the left-top corner of the window in world coordinates
	void getWindowLT(double windowLT[]);

	//! Get the location of the left-bottom corner of the window in world coordinates
	void getWindowLB(double windowLB[]);

	//! Get the location of the right-bottom corner of the window in world coordinates
	void getWindowRB(double windowRB[]);

	//! Updates the perspective frustum based on the stereo mode
	void updatePerspective(stereo_mode m = NONE);

	//! Returns the stereo mode
	stereo_mode getStereoMode();
};

#endif // __YAVRS_CAMERA_H
